quartz: add a default application menu
authorRyan Lortie <desrt@desrt.ca>
Wed, 15 Jan 2014 05:38:02 +0000 (00:38 -0500)
committerRyan Lortie <desrt@desrt.ca>
Sat, 18 Jan 2014 04:14:20 +0000 (23:14 -0500)
When running on quartz, it is no longer expected for applications to
provide their own application menu.  Instead, they should simply ensure
that they provide "app.about", "app.preferences" and "app.quit" actions
(which many apps are already doing).

A default menu will be shown that looks like the one presented by all
other Mac OS applications, containing menu items for the above actions,
as well as the typical "Hide app", "Hide Others and "Show All" items and
the "Services" submenu.

If an application does explicitly set an application menu (via
gtk_application_set_app_menu()) then it will be respected, as before.

https://bugzilla.gnome.org/show_bug.cgi?id=720552

gtk/Makefile.am
gtk/gtk.gresource.xml
gtk/gtkapplication-quartz.c
gtk/gtkapplication-quartz.ui [new file with mode: 0644]
gtk/gtkapplication-quartz.ui.h [new file with mode: 0644]
po/POTFILES.in

index 1c4d2d87f39a44ce5f1a08e536e0e2784de27e9f..06b54ede5a77ea3a3d83c9381c7b5e75d1005002 100644 (file)
@@ -1119,6 +1119,7 @@ DND_CURSORS = \
        cursor_dnd_none.png
 
 COMPOSITE_TEMPLATES =                  \
+       gtkapplication-quartz.ui        \
        gtkaboutdialog.ui               \
        gtkappchooserdialog.ui          \
        gtkappchooserwidget.ui          \
index 549385f2c12cb235f7f8c00029f5c6b28de0c9a5..ae3748628965620787d8665cc9d2b7fc41297f58 100644 (file)
@@ -35,5 +35,6 @@
     <file compressed="true">gtkscalebutton.ui</file>
     <file compressed="true">gtkstatusbar.ui</file>
     <file compressed="true">gtkvolumebutton.ui</file>
+    <file compressed="true">gtkapplication-quartz.ui</file>
   </gresource>
 </gresources>
index 4527f62ece3d6f7239070c37ba260795a51bf651..9b1e0dedbcd0e21916d2a7cc0be06bc2e9470353 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 
 #include "gtkapplicationprivate.h"
+#include "gtkbuilder.h"
 #import <Cocoa/Cocoa.h>
 
 typedef struct
@@ -85,11 +86,44 @@ G_DEFINE_TYPE (GtkApplicationImplQuartz, gtk_application_impl_quartz, GTK_TYPE_A
 }
 @end
 
+/* these exist only for accel handling */
+static void
+gtk_application_impl_quartz_hide (GSimpleAction *action,
+                                  GVariant      *parameter,
+                                  gpointer       user_data)
+{
+  [NSApp hide:NSApp];
+}
+
+static void
+gtk_application_impl_quartz_hide_others (GSimpleAction *action,
+                                         GVariant      *parameter,
+                                         gpointer       user_data)
+{
+  [NSApp hideOtherApplications:NSApp];
+}
+
+static void
+gtk_application_impl_quartz_show_all (GSimpleAction *action,
+                                      GVariant      *parameter,
+                                      gpointer       user_data)
+{
+  [NSApp unhideAllApplications:NSApp];
+}
+
+static GActionEntry gtk_application_impl_quartz_actions[] = {
+  { "hide",             gtk_application_impl_quartz_hide        },
+  { "hide-others",      gtk_application_impl_quartz_hide_others },
+  { "show-all",         gtk_application_impl_quartz_show_all    }
+};
+
 static void
 gtk_application_impl_quartz_startup (GtkApplicationImpl *impl,
                                      gboolean            register_session)
 {
   GtkApplicationImplQuartz *quartz = (GtkApplicationImplQuartz *) impl;
+  GSimpleActionGroup *gtkinternal;
+  GMenuModel *app_menu;
 
   if (register_session)
     {
@@ -100,10 +134,38 @@ gtk_application_impl_quartz_startup (GtkApplicationImpl *impl,
   quartz->muxer = gtk_action_muxer_new ();
   gtk_action_muxer_set_parent (quartz->muxer, gtk_application_get_action_muxer (impl->application));
 
-  /* app menu must come first so that we always see index '0' in
-   * 'combined' as being the app menu.
-   */
-  gtk_application_impl_set_app_menu (impl, gtk_application_get_app_menu (impl->application));
+  /* Add the default accels */
+  gtk_application_add_accelerator (impl->application, "<Primary>comma", "app.preferences", NULL);
+  gtk_application_add_accelerator (impl->application, "<Primary><Alt>h", "gtkinternal.hide-others", NULL);
+  gtk_application_add_accelerator (impl->application, "<Primary>h", "gtkinternal.hide", NULL);
+  gtk_application_add_accelerator (impl->application, "<Primary>q", "app.quit", NULL);
+
+  /* and put code behind the 'special' accels */
+  gtkinternal = g_simple_action_group_new ();
+  g_action_map_add_action_entries (G_ACTION_MAP (gtkinternal), gtk_application_impl_quartz_actions,
+                                   G_N_ELEMENTS (gtk_application_impl_quartz_actions), quartz);
+  gtk_application_insert_action_group (impl->application, "gtkinternal", G_ACTION_GROUP (gtkinternal));
+  g_object_unref (gtkinternal);
+
+  /* now setup the menu */
+  app_menu = gtk_application_get_app_menu (impl->application);
+  if (app_menu == NULL)
+    {
+      GtkBuilder *builder;
+
+      /* If the user didn't fill in their own menu yet, add ours.
+       *
+       * The fact that we do this here ensures that we will always have the
+       * app menu at index 0 in 'combined'.
+       */
+      builder = gtk_builder_new_from_resource ("/org/gtk/libgtk/gtkapplication-quartz.ui");
+      gtk_application_set_app_menu (impl->application, G_MENU_MODEL (gtk_builder_get_object (builder, "app-menu")));
+      g_object_unref (builder);
+    }
+  else
+    gtk_application_impl_set_app_menu (impl, app_menu);
+
+  /* This may or may not add an item to 'combined' */
   gtk_application_impl_set_menubar (impl, gtk_application_get_menubar (impl->application));
 
   /* OK.  Now put it in the menu. */
diff --git a/gtk/gtkapplication-quartz.ui b/gtk/gtkapplication-quartz.ui
new file mode 100644 (file)
index 0000000..efa969e
--- /dev/null
@@ -0,0 +1,54 @@
+<interface>
+  <menu id='app-menu'>
+    <section>
+      <item>
+        <!-- used for the application menu on MacOS.  %s is replaced with the application name. -->
+        <attribute name='label' translatable='yes'>About %s</attribute>
+        <attribute name='action'>app.about</attribute>
+        <attribute name='x-gtk-private-special'>replace-appname</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <!-- used for the application menu on MacOS -->
+        <attribute name='label' translatable='yes'>Preferences</attribute>
+        <attribute name='action'>app.preferences</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <!-- used for the application menu on MacOS -->
+        <attribute name='label' translatable='yes'>Services</attribute>
+        <attribute name='x-gtk-private-special'>services-submenu</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <!-- used for the application menu on MacOS.  %s is replaced with the application name. -->
+        <attribute name='label' translatable='yes'>Hide %s</attribute>
+        <attribute name='x-gtk-private-special'>hide-this</attribute>
+        <attribute name='action'>gtkinternal.hide</attribute>
+      </item>
+      <item>
+        <!-- used for the application menu on MacOS -->
+        <attribute name='label' translatable='yes'>Hide Others</attribute>
+        <attribute name='x-gtk-private-special'>hide-others</attribute>
+        <attribute name='action'>gtkinternal.hide-others</attribute>
+      </item>
+      <item>
+        <!-- used for the application menu on MacOS -->
+        <attribute name='label' translatable='yes'>Show All</attribute>
+        <attribute name='x-gtk-private-special'>show-all</attribute>
+        <attribute name='action'>gtkinternal.show-all</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <!-- used for the application menu on MacOS.  %s is replaced with the application name. -->
+        <attribute name='label' translatable='yes'>Quit %s</attribute>
+        <attribute name='action'>app.quit</attribute>
+        <attribute name='x-gtk-private-special'>replace-appname</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>
diff --git a/gtk/gtkapplication-quartz.ui.h b/gtk/gtkapplication-quartz.ui.h
new file mode 100644 (file)
index 0000000..cf175f1
--- /dev/null
@@ -0,0 +1,7 @@
+N_("About %s");
+N_("Preferences");
+N_("Services");
+N_("Hide %s");
+N_("Hide Others");
+N_("Show All");
+N_("Quit %s");
index ebb535e0c1512d667723478899741c18a10b704e..c09e11e3fb1c932557ddf29f730b05bbc47069dd 100644 (file)
@@ -291,6 +291,7 @@ modules/printbackends/test/gtkprintbackendtest.c
 gtk/gtkaboutdialog.ui.h
 gtk/gtkappchooserdialog.ui.h
 gtk/gtkappchooserwidget.ui.h
+gtk/gtkapplication-quartz.ui.h
 gtk/gtkassistant.ui.h
 gtk/gtkcolorchooserdialog.ui.h
 gtk/gtkcoloreditor.ui.h